﻿using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
using Rosetta.Composition;

namespace Rosetta.Controls
{
    public sealed class TemplateViewer : Grid
    {
        #region Fields

        public static readonly DependencyProperty TemplateProperty = DependencyProperty.Register("Template", typeof(Template), typeof(TemplateViewer), new PropertyMetadata(CompositionTemplateChanged));

        #endregion

        #region Constructors

        static TemplateViewer()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(TemplateViewer), new FrameworkPropertyMetadata(typeof(TemplateViewer)));
        }

        #endregion

        #region Properties

        public Template Template
        {
            get { return (Template)GetValue(TemplateProperty); }
            set { SetValue(TemplateProperty, value); }
        }

        #endregion

        #region Private Methods

        private void UpdateTemplate()
        {
            var template = Template;
            if (template != null)
            {
                var graph = TemplateDepthCalculator.GetGraph(template);

                int columns = graph.Count;
                if (columns > 0)
                {
                    // Check if last column is for outputters
                    if (!(graph.Last().Value[0] is OutputterNode))
                    {
                        columns++;
                    }
                }

                if (columns < 3)
                {
                    columns = 3;
                }

                if (ColumnDefinitions.Count != columns)
                {
                    // TODO: Smarter only update what is needed

                    ColumnDefinitions.Clear();
                    Children.Clear();

                    for (int i = 0; i < columns; i++)
                    {
                        ColumnDefinitions.Add(new ColumnDefinition()); // TODO: Fixed size for first/last?

                        var gridFactory = new FrameworkElementFactory(typeof(UniformGrid));
                        gridFactory.SetValue(UniformGrid.ColumnsProperty, 1);
                        var itemsControl = new ItemsControl {Background = new SolidColorBrush {Color = Color.FromRgb((byte)(i*20), (byte)(i*30), (byte)(i*40))}, ItemsPanel = new ItemsPanelTemplate(gridFactory)};

                        SetColumn(itemsControl, i);

                        Children.Add(itemsControl);
                    }
                }

                for (int i = 0; i < graph.Count; i++)
                {
                    var itemsControl = (ItemsControl)Children[i];
                    var nodes = graph[i + 1];

                    if (itemsControl.Items.Count != nodes.Count)
                    {
                        // TODO: Smarter only update what is needed

                        itemsControl.Items.Clear();

                        foreach (var node in nodes)
                        {
                            itemsControl.Items.Add(node);
                        }
                    }
                }
            }
            else
            {
                // Reset view
                ColumnDefinitions.Clear();
                Children.Clear();
            }
        }

        #endregion

        #region Class Methods

        private static void CompositionTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var viewer = (TemplateViewer)d;
            if (viewer != null)
            {
                viewer.UpdateTemplate();
            }
        }

        #endregion
    }
}